package com.cs797.project;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.telephony.TelephonyManager;
import android.util.Log;

public class HotSpotDataAdapter {

    private static final String TAG = "HotSpotDataAdapter";

    private Context context;
    private HotSpotData hotSpotData;
    private SQLiteDatabase database;

    public HotSpotDataAdapter(Context ctx) {
        this.context = ctx;
    }

    public HotSpotDataAdapter open() throws SQLException {
        hotSpotData = new HotSpotData(context, null);
        database = hotSpotData.getWritableDatabase();
        return this;
    }

    public void close() {
        hotSpotData.close();
    }

    public double getBSLat(String mcc, String mncSId, int lacNId, int cidBId) {
        Cursor cursor = database.rawQuery("SELECT bs_latitude FROM BSInfo WHERE bs_mcc='" + mcc + "' AND bs_mnc_sid='"
                + mncSId + "' AND " + "bs_lac_nid=" + lacNId + " AND bs_cid_bid=" + cidBId, null);

        if (cursor.moveToFirst()) {
            return cursor.getDouble(cursor.getColumnIndex("bs_latitude"));
        }

        return 0;
    }

    public double getBSLon(String mcc, String mncSId, int lacNId, int cidBId) {
        Cursor cursor = database.rawQuery("SELECT bs_longitude FROM BSInfo WHERE bs_mcc='" + mcc + "' AND bs_mnc_sid='"
                + mncSId + "' AND " + "bs_lac_nid=" + lacNId + " AND bs_cid_bid=" + cidBId, null);

        if (cursor.moveToFirst()) {
            return cursor.getDouble(cursor.getColumnIndex("bs_longitude"));
        }

        return 0;
    }

    private long getBSRowId(String mcc, String mncSId, int lacNId, int cidBId, int phoneType) {
        return getBSRowId(mcc, mncSId, lacNId, cidBId, phoneType, Double.MAX_VALUE, Double.MAX_VALUE);
    }

    private long getBSRowId(String mcc, String mncSId, int lacNId, int cidBId, int phoneType, double lat, double lon) {
        Cursor cursor = database.rawQuery("SELECT 1 FROM BSInfo WHERE bs_mcc='" + mcc + "' AND bs_mnc_sid='" + mncSId
                + "' AND " + "bs_lac_nid=" + lacNId + " AND bs_cid_bid=" + cidBId, null);
        // new String[] { mcc, mncSId, String.valueOf(lacNId),
        // String.valueOf(cidBId) });
        boolean exists = (cursor.getCount() > 0);
        cursor.close();

        Log.d(TAG, "Got exists values: " + String.valueOf(exists));

        if (exists) {
            Cursor cRowId = database.rawQuery("SELECT _id FROM BSInfo WHERE bs_mcc='" + mcc + "' AND bs_mnc_sid='"
                    + mncSId + "' AND " + "bs_lac_nid=" + lacNId + " AND bs_cid_bid=" + cidBId, null);

            if (cRowId.moveToFirst()) {
                return cRowId.getLong(cRowId.getColumnIndex("_id"));
            } else {
                return -1;
            }
        }

        if (lat == Double.MAX_VALUE || lon == Double.MAX_VALUE) {
            // Don't add this to the DB
            return -1;
        }

        ContentValues values = new ContentValues(7);
        values.put("is_gsm", (phoneType == TelephonyManager.PHONE_TYPE_GSM) ? 1 : 0);
        values.put("bs_mcc", mcc);
        values.put("bs_mnc_sid", mncSId);
        values.put("bs_lac_nid", lacNId);
        values.put("bs_cid_bid", cidBId);
        values.put("bs_latitude", lat);
        values.put("bs_longitude", lon);

        long ret = -1;

        try {
            Log.d(TAG, "Attempting to insert or throw...");
            ret = database.insertOrThrow("BSInfo", null, values);
        } catch (SQLException se) {
            Log.d(TAG, se.getMessage());
        }

        return ret;

        // return database.insert("BSInfo", null, values);

    }

    public long addMSInfo(String mcc, String mncSId, int lacNId, int cidBId, int phoneType, double bsLat, double bsLon,
            double msLat, double msLon, int signalStrength) {

        long bsRowId = getBSRowId(mcc, mncSId, lacNId, cidBId, phoneType, bsLat, bsLon);

        if (bsRowId == -1) {
            Log.d(TAG, "Failed to find/insert bs row id");
            return -1;
        }

        ContentValues values = new ContentValues(4);
        values.put("bs_id", bsRowId);
        values.put("ms_latitude", msLat);
        values.put("ms_longitude", msLon);
        values.put("ms_signal_strength_dbm", signalStrength);

        Log.d(TAG, "Inserting ms info...");
        return database.insert("MSInfo", null, values);
    }

    public Cursor getSignalDataForBS(String mcc, String mncSId, int lacNId, int cidBId, int phoneType) {
        Log.d(TAG, "Trying to find signal info for given bs...");
        long bsRowId = getBSRowId(mcc, mncSId, lacNId, cidBId, phoneType);

        if (bsRowId == -1) {
            Log.d(TAG, "Failed to find bs row id");
            return null;
        }

        return database.query("MSInfo", new String[] { "ms_latitude", "ms_longitude", "ms_signal_strength_dbm" },
                "bs_id=" + String.valueOf(bsRowId), null, null, null, null);
    }

    public Cursor getBSList() {
        Cursor cursor = database.rawQuery("SELECT bs_mcc, bs_mnc_sid, bs_lac_nid, bs_cid_bid FROM BSInfo", null);

        return cursor;
    }

    public void deleteData() {
        database.execSQL("DELETE FROM MSInfo");
        database.execSQL("DELETE FROM BSInfo");
    }

    public void populateTestData() {
        hotSpotData.dropTables();
        //deleteData();

        List<TestBSData> tdbs = new ArrayList<TestBSData>();
        List<TestMSData> tdms = new ArrayList<TestMSData>();

        tdbs.add(new TestBSData("310", "209", 1234, 3948767, 42.43547, -83.996261));
        tdms.add(new TestMSData(1, 42.44, -83.99, -90));
        tdms.add(new TestMSData(1, 42.46, -83.10, -45));
        tdms.add(new TestMSData(1, 42.43, -83.98, -53));
        tdms.add(new TestMSData(1, 42.43, -83.99, -110));
        tdms.add(new TestMSData(1, 42.43, -84.00, -11));

        tdbs.add(new TestBSData("310", "483", 654321, 29384520, 53.525666, -1.630805));
        tdms.add(new TestMSData(2, 53.52, -1.63, -60));
        tdms.add(new TestMSData(2, 53.51, -1.64, -72));
        tdms.add(new TestMSData(2, 53.52, -1.62, -113));
        tdms.add(new TestMSData(2, 53.52, -1.63, -53));
        tdms.add(new TestMSData(2, 53.51, -1.63, -58));
        tdms.add(new TestMSData(2, 53.54, -1.64, -104));
        tdms.add(new TestMSData(2, 53.52, -1.61, -100));

        tdbs.add(new TestBSData("310", "987", 29385, 6523, 40.038557, -76.105042));
        tdms.add(new TestMSData(3, 40.039706, -76.106157, -62));
        tdms.add(new TestMSData(3, 40.040364, -76.103454, -80));
        tdms.add(new TestMSData(3, 40.040659, -76.104655, -99));
        tdms.add(new TestMSData(3, 40.037045, -76.105771, -101));
        tdms.add(new TestMSData(3, 40.035074, -76.105256, -55));
        tdms.add(new TestMSData(3, 40.036618, -76.101694, -92));
        tdms.add(new TestMSData(3, 40.034088, -76.106715, -88));

        for (TestBSData bsd : tdbs) {
            ContentValues values = new ContentValues(7);
            values.put("is_gsm", 1);
            values.put("bs_mcc", bsd.mcc);
            values.put("bs_mnc_sid", bsd.mnc);
            values.put("bs_lac_nid", bsd.lac);
            values.put("bs_cid_bid", bsd.cid);
            values.put("bs_latitude", bsd.lat);
            values.put("bs_longitude", bsd.lon);

            database.insert("BSInfo", null, values);
        }

        for (TestMSData msd : tdms) {
            ContentValues values = new ContentValues(7);
            values.put("bs_id", msd.rowid);
            values.put("ms_latitude", msd.lat);
            values.put("ms_longitude", msd.lon);
            values.put("ms_signal_strength_dbm", msd.ss);

            database.insert("MSInfo", null, values);
        }

    }

    private class TestBSData {
        public String mcc;
        public String mnc;
        public int lac;
        public int cid;
        public double lat;
        public double lon;

        public TestBSData(String _mcc, String _mnc, int _lac, int _cid, double _lat, double _lon) {
            mcc = _mcc;
            mnc = _mnc;
            lac = _lac;
            cid = _cid;
            lat = _lat;
            lon = _lon;
        }
    }

    private class TestMSData {
        public long rowid;
        public double lat;
        public double lon;
        public int ss;

        public TestMSData(long _rowid, double _lat, double _lon, int _ss) {
            rowid = _rowid;
            lat = _lat;
            lon = _lon;
            ss = _ss;
        }
    }
}
